bitkeeper revision 1.288 (3f098762sqCvcfeLanWC1bkr_aEKGA)
authorrac61@labyrinth.cl.cam.ac.uk <rac61@labyrinth.cl.cam.ac.uk>
Mon, 7 Jul 2003 14:44:50 +0000 (14:44 +0000)
committerrac61@labyrinth.cl.cam.ac.uk <rac61@labyrinth.cl.cam.ac.uk>
Mon, 7 Jul 2003 14:44:50 +0000 (14:44 +0000)
Add virtual disk manager to xenctl
Implement partial virtual disk functionality
Code cleanups

14 files changed:
.rootkeys
tools/control/src/org/xenoserver/cmdline/Main.java
tools/control/src/org/xenoserver/cmdline/ParsePartitionsAdd.java [new file with mode: 0644]
tools/control/src/org/xenoserver/cmdline/ParsePartitionsList.java
tools/control/src/org/xenoserver/cmdline/ParseVdCreate.java [new file with mode: 0644]
tools/control/src/org/xenoserver/cmdline/ParseVdFree.java [new file with mode: 0644]
tools/control/src/org/xenoserver/cmdline/ParseVdShow.java [new file with mode: 0644]
tools/control/src/org/xenoserver/control/CommandPartitionAdd.java [new file with mode: 0644]
tools/control/src/org/xenoserver/control/CommandVdCreate.java [new file with mode: 0644]
tools/control/src/org/xenoserver/control/VirtualBlockDevice.java [new file with mode: 0644]
tools/control/src/org/xenoserver/control/VirtualDisk.java [new file with mode: 0644]
tools/control/src/org/xenoserver/control/VirtualDiskManager.java [new file with mode: 0644]
tools/control/src/org/xenoserver/control/XML.java
tools/control/src/org/xenoserver/control/XMLHelper.java

index 66278fcfa5a40fccc22a3efffa3bfc28522de91e..b9bd14042449e0a37925ef02f264e92782ff96d9 100644 (file)
--- a/.rootkeys
+++ b/.rootkeys
 3f042c35UhRkvblwKSx0KW2QHUn3Fw tools/control/src/org/xenoserver/cmdline/ParseFailedException.java
 3f0445524oTSyogDGmCAyKMM665Rxg tools/control/src/org/xenoserver/cmdline/ParseGroup.java
 3f042c35Inw0LzkOzXo9ncbEHZzUHA tools/control/src/org/xenoserver/cmdline/ParseHelp.java
+3f098761jTSCT4f7lCWFePC3TJN_nw tools/control/src/org/xenoserver/cmdline/ParsePartitionsAdd.java
 3f05631djnPcaqmzMFSa8RLmGCZ-0Q tools/control/src/org/xenoserver/cmdline/ParsePartitionsList.java
 3f05631dswxJX_TpcuG6tBstyHSetg tools/control/src/org/xenoserver/cmdline/ParsePhysicalGrant.java
 3f05631dMY7PMkwSY7zBFelGJ8goVg tools/control/src/org/xenoserver/cmdline/ParsePhysicalList.java
 3f05631dYDFXv6mwNFAgz3ta9kShJA tools/control/src/org/xenoserver/cmdline/ParsePhysicalRevoke.java
+3f098761TRsbDk9woUM846Q6_F7EmA tools/control/src/org/xenoserver/cmdline/ParseVdCreate.java
+3f098761zh9WTV6LpRqcet3gqlXdtg tools/control/src/org/xenoserver/cmdline/ParseVdFree.java
+3f098761vY4hzt_QKskmvMcibN0zYQ tools/control/src/org/xenoserver/cmdline/ParseVdShow.java
 3f042c35V-Bf3dlIe1r5mZs8ZTPSvA tools/control/src/org/xenoserver/control/Command.java
 3f042c35U_4O2eovLKUgo2avPPHKUw tools/control/src/org/xenoserver/control/CommandDomainDestroy.java
 3f042c3570VRwuzl94tEozOIVBycNg tools/control/src/org/xenoserver/control/CommandDomainList.java
 3f042c36GqoXJJj_BvWGwBeKwEzgvg tools/control/src/org/xenoserver/control/CommandDomainStart.java
 3f042c36bmZJD0xrxURD075avUlIUg tools/control/src/org/xenoserver/control/CommandDomainStop.java
 3f042c35hdwL__Airzyz4HutOgGRqQ tools/control/src/org/xenoserver/control/CommandFailedException.java
+3f0987611uZwg-o64yi0p_2aXCYEug tools/control/src/org/xenoserver/control/CommandPartitionAdd.java
 3f05631ev3UK5FRi5vgR08zDp3OZYw tools/control/src/org/xenoserver/control/CommandPhysicalGrant.java
 3f05631e_G6wzHhEnpihX0pIkEsbMw tools/control/src/org/xenoserver/control/CommandPhysicalList.java
 3f05631eGWxq7bojQbMa-tGxsENIhw tools/control/src/org/xenoserver/control/CommandPhysicalRevoke.java
+3f098761c5-idlmf9vWEMOlDw0VCHg tools/control/src/org/xenoserver/control/CommandVdCreate.java
 3eb781fdBRXfSlWzK6GXlIQIlHFoaQ tools/control/src/org/xenoserver/control/Defaults.java
 3ec41f7cQ7Ug739JBDrsVH-7KJ5MvQ tools/control/src/org/xenoserver/control/Domain.java
 3ec41f7cAzdBu0lkuTTQx92rqSM9Qw tools/control/src/org/xenoserver/control/Extent.java
@@ -49,6 +55,9 @@
 3ec41f7djIGkw6M9meq8-YZ1WDATcw tools/control/src/org/xenoserver/control/PartitionManager.java
 3eb781fdmMkFbyb2SAGR0vsuFtl9Lw tools/control/src/org/xenoserver/control/Settings.java
 3eb781fdpgi83RpUvQWVccWjsDJK7w tools/control/src/org/xenoserver/control/StringPattern.java
+3ec41f7dNJZ1YkLD8X5CsqqYmP601g tools/control/src/org/xenoserver/control/VirtualBlockDevice.java
+3ec41f7dVFBlviwXPQ06BlU3UybziA tools/control/src/org/xenoserver/control/VirtualDisk.java
+3ec41f7dKX9YpwrfH7BZ7BogyWqqLA tools/control/src/org/xenoserver/control/VirtualDiskManager.java
 3ec41f7dUPpYTwYL5QVpRBv6PLKPrg tools/control/src/org/xenoserver/control/XML.java
 3ec41f7d7Try-2zmfnpaALwJjY0GCA tools/control/src/org/xenoserver/control/XMLHelper.java
 3ec41f7civcv4mQiYK0DeX9Zvsxhrw tools/control/src/uk/ac/cam/cl/xeno/xenctl/Main.java.orig
index 624a07c951657799afb1780ee12dcae3606e7756..ad58cadb7e17c7a6cffd23a0827180582fbb3d0e 100644 (file)
@@ -1,9 +1,6 @@
 package org.xenoserver.cmdline;
 
-import java.util.Arrays;
-import java.util.Collections;
 import java.util.LinkedList;
-import java.util.List;
 
 import org.xenoserver.control.CommandFailedException;
 import org.xenoserver.control.Defaults;
@@ -18,18 +15,25 @@ public class Main {
       new ParseDomainList()
     };
   static final CommandParser partitioncommands[] =
-    { new ParsePartitionsList()
+    { new ParsePartitionsAdd(),
+      new ParsePartitionsList()
     };
   static final CommandParser physicalcommands[] =
     { new ParsePhysicalGrant(),
       new ParsePhysicalRevoke(),
       new ParsePhysicalList()
     };
+  static final CommandParser vdcommands[] =
+    { new ParseVdCreate(),
+      new ParseVdShow(),
+      new ParseVdFree()
+    };
   static final CommandParser commands[] =
     { help,
       new ParseGroup( "domain", domaincommands ),
       new ParseGroup( "partitions", partitioncommands ),
-      new ParseGroup( "physical", physicalcommands )
+      new ParseGroup( "physical", physicalcommands ),
+      new ParseGroup( "vd", vdcommands )
     };
   static final CommandParser parser = new ParseGroup( null, commands );
 
diff --git a/tools/control/src/org/xenoserver/cmdline/ParsePartitionsAdd.java b/tools/control/src/org/xenoserver/cmdline/ParsePartitionsAdd.java
new file mode 100644 (file)
index 0000000..63f6dce
--- /dev/null
@@ -0,0 +1,56 @@
+package org.xenoserver.cmdline;
+
+import java.util.LinkedList;
+
+import org.xenoserver.control.CommandFailedException;
+import org.xenoserver.control.CommandPartitionAdd;
+import org.xenoserver.control.Defaults;
+import org.xenoserver.control.Library;
+import org.xenoserver.control.Partition;
+import org.xenoserver.control.PartitionManager;
+import org.xenoserver.control.Settings;
+
+public class ParsePartitionsAdd extends CommandParser {
+  public void parse(Defaults d, LinkedList args) throws ParseFailedException, CommandFailedException {
+    boolean force = getFlagParameter(args, 'f');
+    String partition_name = getStringParameter(args, 'p', "");
+    String size = getStringParameter(args, 'c', "100M");
+    
+    if (partition_name.equals(""))
+      throw new ParseFailedException("Expected -p<partition_name>");
+      
+    long chunksize = Library.parse_size( size ) / Settings.SECTOR_SIZE;
+    if ( chunksize <= 0 )
+      throw new CommandFailedException("Chunk size " + size + " is smaller than sector size.");
+    
+    // Initialise the partition manager and look up the partition
+    loadState();
+    Partition p = PartitionManager.it.get_partition(partition_name);
+    
+    if ( p == null )
+      throw new CommandFailedException("Partition " + partition_name + " does not exist.");
+    
+    // Check if this partition belongs to the VDM
+    if (p.getIsXeno() && !force)
+      throw new CommandFailedException("Refusing to add partition as it is already allocated to the virtual disk manager. Use -f if you are sure.");
+    
+    String output = new CommandPartitionAdd( p, chunksize ).execute();
+    if ( output != null )
+      System.out.println( output );
+      
+    saveState();
+  }
+
+  public String getName() {
+    return "add";
+  }
+
+  public String getUsage() {
+    return "[-f] [-p<partition_name>] [-c<chunk_size>]";
+  }
+
+  public String getHelpText() {
+    return "Add the specified partition to the virtual disk manager's free\n" +
+           "space. -c changes the default chunk size. -f forces add.";
+  }
+}
index 02a754f23f876f4e0a70b3b7923342244c46583d..78534614639787f20f9eb6ee5a86db31ab8dfb22 100644 (file)
@@ -8,13 +8,10 @@ import org.xenoserver.control.Defaults;
 import org.xenoserver.control.Library;
 import org.xenoserver.control.Partition;
 import org.xenoserver.control.PartitionManager;
-import org.xenoserver.control.Settings;
-import org.xenoserver.control.XML;
 
 public class ParsePartitionsList extends CommandParser {
-
   public void parse(Defaults d, LinkedList args) throws ParseFailedException, CommandFailedException {
-    XML.load_state( PartitionManager.it, Settings.STATE_INPUT_FILE );
+    loadState();
     Iterator i = PartitionManager.it.iterator();
     int idx = 1;
     System.out.println( "     maj:min " + "    blocks " + "start sect " +
diff --git a/tools/control/src/org/xenoserver/cmdline/ParseVdCreate.java b/tools/control/src/org/xenoserver/cmdline/ParseVdCreate.java
new file mode 100644 (file)
index 0000000..9075039
--- /dev/null
@@ -0,0 +1,49 @@
+package org.xenoserver.cmdline;
+
+import java.util.Date;
+import java.util.LinkedList;
+
+import org.xenoserver.control.CommandFailedException;
+import org.xenoserver.control.CommandVdCreate;
+import org.xenoserver.control.Defaults;
+import org.xenoserver.control.Library;
+import org.xenoserver.control.Settings;
+
+public class ParseVdCreate extends CommandParser {
+  public void parse(Defaults d, LinkedList args) throws ParseFailedException, CommandFailedException {
+    String name = getStringParameter(args,'n',"");
+    String size_s = getStringParameter(args,'s',"");
+    String expiry_s = getStringParameter(args,'e',"");
+    Date expiry;
+    
+    if ( name.equals("") )
+      throw new ParseFailedException("Expected -n<name>");
+    if ( size_s.equals("") )
+      throw new ParseFailedException("Expected -s<size>");
+    if ( expiry_s.equals("") )
+      expiry = null;
+    else
+      expiry = new Date(Date.parse(expiry_s));
+      
+    long size = Library.parse_size(size_s);
+    
+    loadState();
+    String output = new CommandVdCreate(name,size/Settings.SECTOR_SIZE,expiry).execute();
+    if ( output != null )
+      System.out.println( output );
+    saveState();
+  }
+
+  public String getName() {
+    return "create";
+  }
+
+  public String getUsage() {
+    return "[-n<name>] [-s<size>] [-e<expiry>]";
+  }
+
+  public String getHelpText() {
+    return "Create a new virtual disk with the specified parameters";
+  }
+
+}
diff --git a/tools/control/src/org/xenoserver/cmdline/ParseVdFree.java b/tools/control/src/org/xenoserver/cmdline/ParseVdFree.java
new file mode 100644 (file)
index 0000000..7bd3e8a
--- /dev/null
@@ -0,0 +1,45 @@
+package org.xenoserver.cmdline;
+
+import java.util.Iterator;
+import java.util.LinkedList;
+
+import org.xenoserver.control.CommandFailedException;
+import org.xenoserver.control.Defaults;
+import org.xenoserver.control.Extent;
+import org.xenoserver.control.Library;
+import org.xenoserver.control.Settings;
+import org.xenoserver.control.VirtualDisk;
+import org.xenoserver.control.VirtualDiskManager;
+
+public class ParseVdFree extends CommandParser {
+  public void parse(Defaults d, LinkedList args) throws ParseFailedException, CommandFailedException {
+    boolean verbose = getFlagParameter(args, 'v');
+    
+    loadState();
+    VirtualDisk free = VirtualDiskManager.it.getFreeVirtualDisk();
+    System.out.println( "Free disk has " + free.getExtentCount() + " extents totalling "
+                      + Library.format_size(free.getSize()*Settings.SECTOR_SIZE,8,1) );
+    if ( verbose ) {
+      Iterator i = free.iterator();
+      System.out.println("  disk       offset         size");
+      while (i.hasNext()) {
+        Extent e = (Extent) i.next();
+        System.out.println( Library.format(e.getDisk(), 6, 0) + " "
+                          + Library.format(e.getOffset(), 12, 0) + " "
+                          + Library.format(e.getSize(), 12, 0) );
+      }
+    }
+  }
+
+  public String getName() {
+    return "free";
+  }
+
+  public String getUsage() {
+    return "[-v]";
+  }
+
+  public String getHelpText() {
+    return "Show free space allocated to virtual disk manager. -v enables verbose output.";
+  }
+}
diff --git a/tools/control/src/org/xenoserver/cmdline/ParseVdShow.java b/tools/control/src/org/xenoserver/cmdline/ParseVdShow.java
new file mode 100644 (file)
index 0000000..287a246
--- /dev/null
@@ -0,0 +1,66 @@
+package org.xenoserver.cmdline;
+
+import java.util.Iterator;
+import java.util.LinkedList;
+
+import org.xenoserver.control.CommandFailedException;
+import org.xenoserver.control.Defaults;
+import org.xenoserver.control.Extent;
+import org.xenoserver.control.Library;
+import org.xenoserver.control.Settings;
+import org.xenoserver.control.VirtualDisk;
+import org.xenoserver.control.VirtualDiskManager;
+
+public class ParseVdShow extends CommandParser {
+  public void parse(Defaults d, LinkedList args) throws ParseFailedException, CommandFailedException {
+    int vd_num = getIntParameter(args,'n',-1);
+    
+    loadState();
+    
+    if ( vd_num < 0 ) {
+      System.out.println("num key        expiry                       name                 size");
+      for (int i=0;i<VirtualDiskManager.it.getVirtualDiskCount();i++) {
+        VirtualDisk vd = VirtualDiskManager.it.getVirtualDisk(i);
+        System.out.print( Library.format(i,3,0) + " " + vd.getKey() + " " );
+        if ( vd.getExpiry() != null )
+          System.out.print( vd.getExpiry().toString() );
+        else
+          System.out.print( "                            " );
+        System.out.println( " " + Library.format(vd.getName(),16,1) + " "
+                          + Library.format_size(vd.getSize()*Settings.SECTOR_SIZE,8,0) );
+      }
+    } else {
+      VirtualDisk vd = VirtualDiskManager.it.getVirtualDisk(vd_num);
+      if ( vd == null )
+        throw new CommandFailedException("There is no virtual disk " + vd_num );
+        
+      System.out.println("  name: " + vd.getName());
+      System.out.println("   key: " + vd.getKey());
+      System.out.println("  size: " + Library.format_size(vd.getSize()*Settings.SECTOR_SIZE,8,1));
+      if ( vd.getExpiry() != null )
+        System.out.println("expiry: " + vd.getExpiry());
+      System.out.println();
+      Iterator i = vd.iterator();
+      System.out.println("  disk       offset         size");
+      while (i.hasNext()) {
+        Extent e = (Extent) i.next();
+        System.out.println( Library.format(e.getDisk(), 6, 0) + " "
+                          + Library.format(e.getOffset(), 12, 0) + " "
+                          + Library.format(e.getSize(), 12, 0) );
+      }
+    }
+  }
+
+  public String getName() {
+    return "show";
+  }
+
+  public String getUsage() {
+    return "[-n<diskno>]";
+  }
+
+  public String getHelpText() {
+    return "Show a summary of all virtual disks, or details of one disk if -n is given";
+  }
+}
diff --git a/tools/control/src/org/xenoserver/control/CommandPartitionAdd.java b/tools/control/src/org/xenoserver/control/CommandPartitionAdd.java
new file mode 100644 (file)
index 0000000..4a2a9c8
--- /dev/null
@@ -0,0 +1,22 @@
+package org.xenoserver.control;
+
+public class CommandPartitionAdd extends Command {
+  private Partition partition;
+  private long chunksize;
+  
+  /**
+   * Constructor for CommandPartitionAdd.
+   * @param partition Partition to add.
+   * @param chunksize Chunk size to split partition into (in sectors).
+   */
+  public CommandPartitionAdd(Partition partition, long chunksize) {
+    this.partition = partition;
+    this.chunksize = chunksize;
+  }
+
+  public String execute() throws CommandFailedException {
+    VirtualDiskManager.it.add_xeno_partition(partition,chunksize);
+    PartitionManager.it.add_xeno_partition(partition);
+    return "Added partition " + partition.getName();
+  }
+}
diff --git a/tools/control/src/org/xenoserver/control/CommandVdCreate.java b/tools/control/src/org/xenoserver/control/CommandVdCreate.java
new file mode 100644 (file)
index 0000000..f9b46cf
--- /dev/null
@@ -0,0 +1,28 @@
+package org.xenoserver.control;
+
+import java.util.Date;
+
+public class CommandVdCreate extends Command {
+  private String name;
+  private long size;
+  private Date expiry;
+
+  /**
+   * Constructor for CommandVdCreate.
+   * @param name Name of new virtual disk.
+   * @param size Size in sectors.
+   * @param expiry Expiry time, or null for never.
+   */
+  public CommandVdCreate(String name, long size, Date expiry) {
+    this.name = name;
+    this.size = size;
+    this.expiry = expiry;
+  }
+
+  public String execute() throws CommandFailedException {
+    VirtualDisk vd = VirtualDiskManager.it.create_virtual_disk(name,size,expiry);
+    if ( vd == null )
+      throw new CommandFailedException( "Not enough free space to create disk" );
+    return "Virtual Disk created with key: " + vd.getKey();
+  }
+}
diff --git a/tools/control/src/org/xenoserver/control/VirtualBlockDevice.java b/tools/control/src/org/xenoserver/control/VirtualBlockDevice.java
new file mode 100644 (file)
index 0000000..c2e8007
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * VirtualBlockDevice.java
+ * 03.03.27 aho creation
+ */
+
+package org.xenoserver.control;
+
+import java.io.PrintWriter;
+
+public class VirtualBlockDevice {
+  String key;
+  int domain;
+  int vbdnum;
+  Mode mode; /* rw or ro */
+
+  String dump(boolean title) {
+    StringBuffer sb = new StringBuffer();
+
+    if (title) {
+      sb.append("  key         dom vbd mode\n");
+    } else {
+      sb.append(
+        "  "
+          + key
+          + "  "
+          + Library.format(domain, 3, 0)
+          + " "
+          + Library.format(vbdnum, 3, 0)
+          + " "
+          + mode.toString()
+          + "\n");
+    }
+
+    return sb.toString();
+  }
+
+  void dump_xml(PrintWriter out) {
+    out.println("  <virtual_block_device>");
+    out.println("    <key>" + key + "</key>");
+    out.println("    <domain>" + domain + "</domain>");
+    out.println("    <vbdnum>" + vbdnum + "</vbdnum>");
+    out.println("    <mode>" + mode + "</mode>");
+    out.println("  </virtual_block_device>");
+  }
+
+  public String getKey() {
+    return key;
+  }
+
+  public int getDomain() {
+    return domain;
+  }
+
+  public int getVBDNum() {
+    return vbdnum;
+  }
+
+  public Mode getMode() {
+    return mode;
+  }
+}
diff --git a/tools/control/src/org/xenoserver/control/VirtualDisk.java b/tools/control/src/org/xenoserver/control/VirtualDisk.java
new file mode 100644 (file)
index 0000000..460570f
--- /dev/null
@@ -0,0 +1,181 @@
+/*
+ * VirtualDisk.java
+ * 03.03.26 aho creation
+ */
+
+package org.xenoserver.control;
+
+import java.io.PrintWriter;
+import java.util.Date;
+import java.util.Iterator;
+import java.util.Vector;
+
+public class VirtualDisk {
+  String name;
+  String key;
+  Date expiry;
+  Vector extents;
+
+  VirtualDisk(String name, Date expiry, String key) {
+    this.name = name;
+    if ( key == null )
+      this.key = generate_key();
+    else
+      this.key = key;
+    this.expiry = expiry;
+    extents = new Vector();
+  }
+
+  VirtualDisk(String name) {
+    this(name, null, null);
+  }
+
+  VirtualDisk(String name, Date expiry) {
+    this(name, expiry, null);
+  }
+
+  /*
+   * generate a unique key for this virtual disk.
+   * for now, just generate a 10 digit number
+   */
+  String generate_key() {
+    return Long.toString(1000000000l + (long) (Math.random() * 8999999999l));
+  }
+
+  void set_expiry(Date expiry) {
+    this.expiry = expiry;
+  }
+
+  public void add_extent(Extent extent) {
+    extents.add(extent);
+  }
+
+  public Extent remove_extent() {
+    Extent e;
+
+    if (extents.size() > 0) {
+      e = (Extent) extents.remove(0);
+    } else {
+      e = null;
+    }
+
+    return e;
+  }
+
+  String dump_xen(VirtualBlockDevice vbd) {
+    StringBuffer sb = new StringBuffer();
+
+    sb.append(
+      "domain:"
+        + vbd.domain
+        + " "
+        + vbd.mode.toString()
+        + " "
+        + "segment:"
+        + vbd.vbdnum
+        + " "
+        + "extents:"
+        + extents.size()
+        + " ");
+    for (int loop = 0; loop < extents.size(); loop++) {
+      Extent e = (Extent) extents.get(loop);
+      sb.append(
+        "(disk:"
+          + e.disk
+          + " "
+          + "offset:"
+          + e.offset
+          + " "
+          + "size:"
+          + e.size
+          + ")");
+    }
+    return sb.toString();
+  }
+
+  void dump_xml(PrintWriter out) {
+    out.println("  <virtual_disk>");
+    out.println("    <name>" + name + "</name>");
+    out.println("    <key>" + key + "</key>");
+    if (expiry == null) {
+      out.println("    <expiry>0</expiry>");
+    } else {
+      out.println("    <expiry>" + expiry.getTime() + "</expiry>");
+    }
+    out.println("    <extents>");
+    for (int loop = 0; loop < extents.size(); loop++) {
+      Extent e = (Extent) extents.get(loop);
+      out.println("      <extent>");
+      out.println("        <disk>" + e.disk + "</disk>");
+      out.println("        <size>" + e.size + "</size>");
+      out.println("        <offset>" + e.offset + "</offset>");
+      out.println("      </extent>");
+    }
+    out.println("    </extents>");
+    out.println("  </virtual_disk>");
+
+    return;
+  }
+
+  /*
+   * Add a partition as a XenoPartition.
+   * Chop the partition in to extents and of size "size" sectors
+   * and add them to the virtual disk.
+   */
+
+  void add_new_partition(Partition partition, long size) {
+    int loop;
+
+    for (loop = 0; loop < partition.nr_sects / size; loop++) {
+      Extent extent = new Extent();
+
+      extent.disk = partition.major << 8;
+      extent.disk = extent.disk | (partition.minor >> 5) << 5;
+      extent.size = size;
+      extent.offset = partition.start_sect + (size * loop);
+
+      add_extent(extent);
+    }
+
+    return;
+  }
+
+  public String getName() {
+    return name;
+  }
+
+  public String getKey() {
+    return key;
+  }
+
+  public Date getExpiry() {
+    return expiry;
+  }
+
+  public int getExtentCount() {
+    return extents.size();
+  }
+
+  public Extent getExtent(int index) {
+    return (Extent) extents.get(index);
+  }
+
+  /**
+   * @return Total size of this virtual disk in sectors.
+   */
+  public long getSize() {
+    long size = 0;
+    Iterator i = extents.iterator();
+    while ( i.hasNext() ) {
+      size += ((Extent) i.next()).getSize();
+    }
+    return size;
+  }
+  
+  /**
+   * @return An iterator over all extents in the disk.
+   */
+  public Iterator iterator() {
+    return extents.iterator();
+  }
+}
diff --git a/tools/control/src/org/xenoserver/control/VirtualDiskManager.java b/tools/control/src/org/xenoserver/control/VirtualDiskManager.java
new file mode 100644 (file)
index 0000000..e2d1e6d
--- /dev/null
@@ -0,0 +1,236 @@
+/*
+ * VirtualDiskManager.java
+ * 03.03.26 aho creation
+ */
+
+package org.xenoserver.control;
+
+import java.io.PrintWriter;
+import java.util.Date;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Vector;
+
+/**
+ * VirtualDiskManager manages the list of virtual disks on the machine. It is
+ * a Singleton which automatically initialises itself on first class reference.
+ */
+public class VirtualDiskManager {
+  public static final VirtualDiskManager it = new VirtualDiskManager();
+  VirtualDisk free_disk;
+  Vector virtual_disks;
+  Hashtable virtual_block_devices;
+  Hashtable key_hash;
+
+  private VirtualDiskManager() {
+    free_disk = new VirtualDisk("free");
+
+    virtual_disks = new Vector(10, 5);
+    flush_virtual_block_devices();
+    key_hash = new Hashtable(100);
+  }
+
+  public VirtualDisk get_virtual_disk_key(String key) {
+    return ((VirtualDisk) key_hash.get(key));
+  }
+
+  public void add_xeno_partition(Partition partition, long size) {
+    free_disk.add_new_partition(partition, size);
+    return;
+  }
+
+  /*
+   * create a new virtual disk
+   */
+
+  public VirtualDisk create_virtual_disk(String name, long size, Date expiry) {
+    VirtualDisk vd = new VirtualDisk(name, expiry);
+
+    if ( free_disk.getSize() < size )
+      return null;
+    
+    while (size > 0) {
+      Extent e;
+
+      e = free_disk.remove_extent();
+      if (e == null) {
+        return null;
+      }
+      size -= e.size;
+      vd.add_extent(e);
+    }
+
+    add_virtual_disk(vd);
+
+    return vd;
+  }
+
+  /*
+   * delete a new virtual disk.  extents go back into the free pool
+   */
+
+  public void delete_virtual_disk(String key) {
+    VirtualDisk vd;
+
+    vd = (VirtualDisk) key_hash.get(key);
+    if (vd != null) {
+      Extent e;
+
+      key_hash.remove(key);
+      virtual_disks.remove(vd);
+
+      e = vd.remove_extent();
+      while (e != null) {
+        free_disk.add_extent(e);
+        e = vd.remove_extent();
+      }
+    }
+    return;
+  }
+
+  /*
+   * reset the expiry time for a virtual disk
+   */
+
+  public void refresh_virtual_disk(String key, Date expiry) {
+    VirtualDisk vd = (VirtualDisk) key_hash.get(key);
+    if (vd != null) {
+      vd.set_expiry(expiry);
+    }
+  }
+
+  /*
+   * create a new virtual block device
+   */
+  public VirtualBlockDevice create_virtual_block_device(
+    String key,
+    int domain,
+    int vbd_num,
+    String mode) {
+    VirtualBlockDevice vbd = new VirtualBlockDevice();
+    VirtualDisk vd = get_virtual_disk_key(key);
+
+    if (vd == null) {
+      System.err.println(
+        "create virtual block device error: unknown key " + "[" + key + "]");
+      return null;
+    }
+
+    vbd.key = key;
+    vbd.domain = domain;
+    vbd.vbdnum = vbd_num;
+
+    if (mode.equals(Mode.READ_ONLY.toString())
+      || mode.equals("RO")
+      || mode.equals("ro")) {
+      vbd.mode = Mode.READ_ONLY;
+    } else if (
+      mode.equals(Mode.READ_WRITE.toString())
+        || mode.equals("RW")
+        || mode.equals("rw")) {
+      vbd.mode = Mode.READ_WRITE;
+    } else {
+      System.err.println(
+        "create virtual block device error: unknown mode " + "[" + mode + "]");
+      return null;
+    }
+
+    add_virtual_block_device(vbd);
+
+    return vbd;
+  }
+
+  /*
+   * delete a virtual block device 
+   */
+  public void delete_virtual_block_device(int domain, int vbd_num) {
+    Object hash = get_vbd_hash(domain, vbd_num);
+    virtual_block_devices.remove(hash);
+  }
+
+  /*
+   * flush all virtual block devices
+   */
+  public void flush_virtual_block_devices() {
+    /* isn't automatic garbage collection wonderful? */
+    virtual_block_devices = new Hashtable(100);
+  }
+
+  public void add_virtual_disk(VirtualDisk vd) {
+    virtual_disks.add(vd);
+    key_hash.put(vd.getKey(), vd);
+  }
+
+  public void add_virtual_block_device(VirtualBlockDevice vbd) {
+    Object hash = get_vbd_hash(vbd.domain, vbd.vbdnum);
+    virtual_block_devices.put(hash, vbd);
+  }
+
+  Object get_vbd_hash(int domain, int vbd_num) {
+    return new Integer(domain * 16 + vbd_num);
+  }
+
+  public void add_free(VirtualDisk vd) {
+    free_disk = vd;
+  }
+
+  public String dump_virtualblockdevices() {
+    StringBuffer sb = new StringBuffer();
+    boolean first = true;
+
+    for (Enumeration enumeration = virtual_block_devices.elements();
+      enumeration.hasMoreElements();
+      ) {
+      VirtualBlockDevice vbd = (VirtualBlockDevice) enumeration.nextElement();
+      if (first) {
+        sb.append(vbd.dump(true));
+        first = false;
+      }
+
+      sb.append(vbd.dump(false));
+    }
+
+    return sb.toString();
+  }
+
+  public void dump_xml(PrintWriter out) {
+    out.println("<free>");
+    free_disk.dump_xml(out);
+    out.println("</free>");
+    out.println("<virtual_disks>");
+    for (int i = 0; i < virtual_disks.size(); i++) {
+      VirtualDisk vd = (VirtualDisk) virtual_disks.get(i);
+      vd.dump_xml(out);
+    }
+    out.println("</virtual_disks>");
+    out.println("<virtual_block_devices>");
+    for (Enumeration enumeration = virtual_block_devices.elements();
+      enumeration.hasMoreElements();
+      ) {
+      VirtualBlockDevice vbd = (VirtualBlockDevice) enumeration.nextElement();
+      vbd.dump_xml(out);
+    }
+
+    out.println("</virtual_block_devices>");
+
+    return;
+  }
+
+  /*************************************************************************/
+
+  public int getVirtualDiskCount() {
+    return virtual_disks.size();
+  }
+
+  public VirtualDisk getVirtualDisk(int index) {
+    return (VirtualDisk) virtual_disks.get(index);
+  }
+
+  public VirtualDisk getFreeVirtualDisk() {
+    return free_disk;
+  }
+
+  public Enumeration getVirtualBlockDevices() {
+    return virtual_block_devices.elements();
+  }
+}
index d8331b9c2be4287c988eb50ca872ab1e9a8854fc..55bc3a9c122002bbef0eb798dbfd996b5bd65993 100644 (file)
@@ -30,7 +30,7 @@ XML
    */
 
   public static void
-  dump_state (PartitionManager pm,/* VirtualDiskManager vdm,*/ String filename)
+  dump_state (PartitionManager pm, VirtualDiskManager vdm, String filename)
   {
     PrintWriter out;
 
@@ -48,7 +48,7 @@ XML
     out.println("<?xml version=\"1.0\"?>");
     out.println("<vdmanager>");
     pm.dump_xml(out);
-    //vdm.dump_xml(out);
+    vdm.dump_xml(out);
     out.println("</vdmanager>");
 
     out.close();
@@ -59,14 +59,14 @@ XML
    * load partition manager and virtual disk manager state from filename
    */
   public static void
-  load_state (PartitionManager pm, /*VirtualDiskManager vdm,*/ String filename)
+  load_state (PartitionManager pm, VirtualDiskManager vdm, String filename)
   {
     if (document == null)
     {
       load_file (filename);
     }
 
-    XMLHelper.parse(pm, /*vdm,*/ document);
+    XMLHelper.parse(pm, vdm, document);
   }
 
   /*
index 5646e5ce212ffcb1b4d0e1975ad1e59a3b609a88..ad1c3f50e18823fae685a8f043cc4fbbed79517a 100644 (file)
@@ -6,6 +6,7 @@
 package org.xenoserver.control;
 
 import java.util.Date;
+
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
 import org.w3c.dom.Node;
@@ -98,14 +99,14 @@ XMLHelper
   }
 
   static void
-  parse (PartitionManager pm, /*VirtualDiskManager vdm,*/ Document document)
+  parse (PartitionManager pm, VirtualDiskManager vdm, Document document)
   {
     if (document == null) return;
 
     /* parse partitions */
     parse_partitions(pm, document.getElementsByTagName("partition"));
-/*
-    / parse virtual disks /
+
+    /* parse virtual disks */
     NodeList list = document.getElementsByTagName("virtual_disk");
     for (int i = 0; i < list.getLength(); i++)
     {
@@ -128,20 +129,24 @@ XMLHelper
       }
     }
 
-    / parse virtual block devices /
+    /* parse virtual block devices */
     parse_virtual_block_devices(vdm, document.getElementsByTagName("virtual_block_device"));
-*/
+
     return;
   }
 
/* static VirtualDisk
+  static VirtualDisk
   parse_virtual_disk(Node node)
   {
     VirtualDisk vd;
     Date date = new Date();
     NodeList list;
 
-    date.setTime(Long.parseLong(XMLHelper.get_text(XMLHelper.get_subnode("expiry", node))));
+    long timestamp = Long.parseLong(XMLHelper.get_text(XMLHelper.get_subnode("expiry", node)));
+    if ( timestamp == 0 )
+      date = null;
+    else
+      date.setTime( timestamp );
     vd = new VirtualDisk(XMLHelper.get_text(XMLHelper.get_subnode("name", node)),
                         date,
                         XMLHelper.get_text(XMLHelper.get_subnode("key", node)));
@@ -164,7 +169,7 @@ XMLHelper
     }
 
     return vd;
-  }*/
+  }
 
   static void
   parse_partitions (PartitionManager pm, NodeList nl)
@@ -186,12 +191,10 @@ XMLHelper
       pm.add_xeno_partition(partition);
     }
   }
-/*
+
   static void
   parse_virtual_block_devices (VirtualDiskManager vdm, NodeList nl)
   {
-    VirtualBlockDevice vbd;
-
     for (int loop = 0; loop < nl.getLength(); loop++)
     {
       Node node = nl.item(loop);
@@ -201,5 +204,5 @@ XMLHelper
                                      Integer.parseInt(XMLHelper.get_text(XMLHelper.get_subnode("vbdnum", node))),
                                      XMLHelper.get_text(XMLHelper.get_subnode("mode", node)));
     }
-  }*/
+  }
 }